import { getLoadingControl } from "@/components/loading";
import { showToast } from "@/components/toast";
import { sleep } from "@/utils/base";
import { request } from "@/utils/request";
import { AxiosRequestConfig } from "axios";
import { useCallback, useRef, useState } from "react";

type ResData = {
  data: Obj;
  message: string;
  success: boolean;
};

type Options = {
  silent?: boolean;
  isWaitTips?: boolean;
  isOpenLoading?: boolean;
  axiosOptions?: AxiosRequestConfig;
};

export function useHttp() {
  const [isLoading, setIsLoading] = useState<boolean>(false);

  const { openLoading, closeLoading } = getLoadingControl();

  const hideLoading = async (options: Options) => {
    await sleep(0.5);
    setIsLoading(false);
    options.isOpenLoading && closeLoading();
  };

  const showLoading = (options: Options) => {
    setIsLoading(true);
    options.isOpenLoading && openLoading();
  };

  const showTips = async (options: Options, res: ResData) => {
    if (!options.silent) {
      !options.isWaitTips
        ? showToast(res.message)
        : await new Promise((resolve) =>
            showToast({
              message: res.message,
              duration: 2000,
              onClose: resolve,
            })
          );
    }
  };

  const commonRef = useRef({
    hideLoading,
    showLoading,
    showTips,
  });

  const get = useCallback(
    async (url: string, params = {}, options: Options = {}) => {
      commonRef.current.showLoading(options);

      try {
        const res = await request.get<ResData, ResData>(url, {
          params,
          ...(options.axiosOptions || {}),
        });

        await commonRef.current.hideLoading(options);
        commonRef.current.showTips(options, res);

        return res;
      } catch (err) {
        console.log("[useHttp]:", url, err);
        commonRef.current.hideLoading(options);
        return null;
      }
    },
    []
  );

  const post = useCallback(
    async (url: string, data = {}, options: Options = {}) => {
      commonRef.current.showLoading(options);

      try {
        const res = await request.post<ResData, ResData>(url, data, {
          ...(options.axiosOptions || {}),
        });
        await commonRef.current.hideLoading(options);
        commonRef.current.showTips(options, res);

        return res;
      } catch (err) {
        console.log("[useHttp]:", url, err);
        commonRef.current.hideLoading(options);
        return null;
      }
    },
    []
  );

  const httpRef = useRef({
    get,
    post,
  });

  return { isLoading, http: httpRef.current };
}
